﻿

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Linq;

namespace Unis.Framework.Core.Utility
{
    public static class Extensions
    {
        public static bool IsNullOrDefault<T>(this T? value) where T : struct
        {
            return default(T).Equals(value.GetValueOrDefault());
        }

        public static List<T2> CopyDataTo<T1, T2>(this IList<T1> target)
        {
            var resultT2List = new List<T2>();

            if (target != null)
            {
                foreach (T1 t1 in target)
                {
                    T2 t2 = System.Activator.CreateInstance<T2>();

                    foreach (PropertyInfo item in typeof(T1).GetProperties())
                    {
                        object ret = item.GetValue(t1, null);
                        if (item.Name != "EntityState" && item.Name != "Selected")
                        {
                            if (typeof(T2).GetProperty(item.Name) != null)
                            {
                                typeof(T2).GetProperty(item.Name).SetValue(t2, ret, null);
                            }
                        }

                    }
                    resultT2List.Add(t2);
                }
            }
            return resultT2List;
        }




        public static List<T> CopyTo<T>(this List<T> formList, List<T> toList)
        {
            if (default(List<T>) == toList)
            {
                toList = new List<T>();
            }
            toList.AddRange(formList);

            return toList;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public static DataTable ListToDataTable(this IList list)
        {
            var result = new DataTable();
            if (list.Count > 0)
            {
                PropertyInfo[] propertys = list[0].GetType().GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    result.Columns.Add(pi.Name, pi.PropertyType);
                }

                for (int i = 0; i < list.Count; i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (PropertyInfo pi in propertys)
                    {
                        object obj = pi.GetValue(list[i], null);
                        tempList.Add(obj);
                    }
                    object[] array = tempList.ToArray();
                    result.LoadDataRow(array, true);
                }
            }
            return result;
        }

        /// <summary>
        /// 将DataTable转换成List泛型集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static List<T> DataTableToList<T>(this DataTable dt) where T : new()
        {
            try
            {
                // 定义集合
                List<T> ts = new List<T>();

                // 获得此模型的类型
                Type type = typeof(T);

                string tempName = "";

                foreach (DataRow dr in dt.Rows)
                {
                    T t = new T();

                    // 获得此模型的公共属性
                    PropertyInfo[] propertys = t.GetType().GetProperties();

                    foreach (PropertyInfo pi in propertys)
                    {
                        if (pi.PropertyType.FullName.Contains("Int32") || pi.PropertyType.FullName.Contains("Int16")
                            || pi.PropertyType.FullName.Contains("Decimal") || pi.PropertyType.FullName.Contains("Boolean")
                            || pi.PropertyType.FullName.Contains("DateTime") || pi.PropertyType.FullName.Contains("Nullable")
                            || pi.PropertyType.FullName.Contains("String"))//各种预知类型判定
                        {
                            tempName = pi.Name;

                            // 检查DataTable是否包含此列
                            if (dt.Columns.Contains(tempName))
                            {
                                // 判断此属性是否有Setter
                                if (!pi.CanWrite) continue;




                                object value = dr[tempName];


                                if (value.GetType().FullName == "System.Guid")
                                    value = value.ToString();
                                if (value != DBNull.Value)
                                    pi.SetValue(t, value, null);
                            }
                        }
                    }

                    ts.Add(t);
                }

                return ts;
            }
            catch
            {
                return null;
            }

        }

        public static T Clone<T>(this T realObject)
        {
            using (Stream objectStream = new MemoryStream())
            {
                IFormatter formatter = new BinaryFormatter();
                formatter.Serialize(objectStream, realObject);
                objectStream.Seek(0, SeekOrigin.Begin);
                return (T)formatter.Deserialize(objectStream);
            }
        }

        /// <summary>
        /// 在2的次方中计算拥有指定属性的集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="propertyName"></param>
        /// <param name="compareValue"></param>
        /// <returns></returns>
        public static List<T> ExitPowerList<T>(this List<T> list, string propertyName, decimal compareValue, bool catched) where T : class
        {
            if (list == null || list.Count == 0)
                return list;
            var tempList = new List<T>();
            try
            {
                //list.ForEach(t =>
                //{
                //    object obj = typeof(T).GetProperty(propertyName).GetValue(t, null);
                //    bool isExit = PowerCalculateCommon.PowerCalculateV(Convert.ToDecimal(obj), (int)compareValue);
                //    if (isExit)
                //        tempList.Add(t);
                //});
                tempList.AddRange(list.Where(item => PowerCalculateCommon.PowerCalculateV(
                    Reflection.GetObjectProperty(item, propertyName) == null ? -99 : Convert.ToDecimal(Reflection.GetObjectProperty(item, propertyName)), (int)compareValue) == catched));
            }
            catch
            {
            }

            return tempList;
        }

        /// <summary>
        /// 获取枚举类型的Description属性的描述
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="enumObj"></param>
        /// <returns></returns>
        public static string GetEnumDescription<T>(this Enum enumObj)
        {
            FieldInfo fieldInfo = typeof(T).GetField(enumObj.ToString());
            if (fieldInfo != null)
            {
                var descriptionAttribute = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), true)[0]
                                                            as DescriptionAttribute;
                if (descriptionAttribute != null)
                    return descriptionAttribute.Description;
            }
            return "";
        }

        public static T GetXmlAttributeValue<T>(this XElement element, string key) where T : IConvertible
        {
            var attry = element.Attribute(key);
            if (attry == null) return default(T);
            return (T)Convert.ChangeType(attry.Value, typeof(T));
        }

        /// <summary>
        /// 利用反射来判断对象是否包含某个属性
        /// </summary>
        /// <param name="instance">object</param>
        /// <param name="propertyName">需要判断的属性</param>
        /// <returns>是否包含</returns>
        public static bool ContainProperty(this object instance, string propertyName)
        {
            if (instance != null && !string.IsNullOrEmpty(propertyName))
            {
                PropertyInfo _findedPropertyInfo = instance.GetType().GetProperty(propertyName);
                return (_findedPropertyInfo != null);
            }
            return false;
        }

    }
}
